home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / MSTPChart / MacSciTechDemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-26  |  22.3 KB  |  592 lines  |  [TEXT/KAHL]

  1. /*
  2. •        This THINK C source code, project file, and resource file were created by
  3. •        Dr. Craig Stone, Professor of Nuclear Chemistry at San Jose State
  4. •        University, California USA, for the Macintosh Scientific and Technical
  5. •        Users Association (MacSciTech), to accompany his article "Quickstart
  6. •        Macintosh Programming" which appeared in the SciTech Journal of May, 1993.
  7. •        Supplemental commenting was added by MacSciTech. The author
  8. •        can be reached on Applelink at Stone.C. MacSciTech can be reached on
  9. •        Applelink at MacSciTech, on America Online at SciTechMac, and on the
  10. •        Internet at SciTechMac@aol.com or attila.nrl.navy.mil. You are encouraged
  11. •        to use, modify, and improve this source code without restriction. If you
  12. •        distribute this source code essentially unmodified and for public
  13. •        consumption (e.g., you post it to a BBS), MacSciTech does request that
  14. •        you leave the comments intact and keep all the project files together:
  15. •        About.c
  16. •        Elements.c
  17. •        MacSciTechDemo.c
  18. •        MenuControl.c
  19. •        Periodic.c
  20. •        WindowControl.c
  21. •        MST_Defines.h
  22. •        MST_Externs.h
  23. •        MST_Globals.h
  24. •        MST_Menus.h
  25. •        MST_Prototypes.h
  26. •        MSTPChart.π
  27. •        MSTPChart.π.rsrc
  28. •        All functions are "marked," so you can quickly navigate to any function
  29. •        in a file by pressing the mouse down in the title bar of the source
  30. •        code window while holding down the command key. This presents you with
  31. •        a pop-up menu of all the functions. Similarly, all the include files
  32. •        are available by holding down the option key while pressing the mouse
  33. •        down in the title bar.
  34. •        
  35. */ 
  36.  
  37.  
  38.  
  39. /*
  40. •        This file contains the function "main", which is the point at which
  41. •        our program begins execution.
  42. */
  43.  
  44. /*
  45. •        We include two files up front. The file MST_Defines.h contains our constants.
  46. •        MST_Globals.h defines (i.e., declares the type of and allocates
  47. •        storage for) our global variables.
  48. */
  49.  
  50. #include    "MST_Defines.h"
  51. #include    "MST_Globals.h"
  52.  
  53.  
  54. void    Init_Variables    (void); /*Declare Init_Variables() here for aesthetic reasons:*/
  55.                                 /*main() can refer to it, yet we can place main() at*/
  56.                                 /*the top of the source file where it is handy.*/
  57.                                 
  58.  
  59. /*_____________________________________________________________________________
  60.                         main()- main program
  61. _____________________________________________________________________________*/
  62.  
  63. void main() 
  64. {
  65.  
  66. /*
  67. •    Any program does two things. It initializes itself, and then enters into
  68. •    an event loop until the user asks it to quit. Often the main() function
  69. •    of a program places the initialization routines in a separate source
  70. •    code file, and the event loop in another file, so that the main()
  71. •    code is exceptionally short. Since our program is not very complex, we
  72. •    will keep most of the initialization and the event loop in main().
  73. •    Here we declare our variables for main(). The variables are:
  74. •    stillInGoAway    
  75. •    thisChar        
  76. •    thisCode        
  77. •    thisMenu        
  78. •    thisItem        
  79. •    MainKey            
  80. •    thisResult        Store information about the menu item selected here
  81. •    thisRect        A boundary rectangle so we cannot drag our window off the screen
  82. •    theInput        
  83. •    thisEvent        
  84. •    thisWindow        
  85. */
  86.  
  87.     char            stillInGoAway,    thisChar;
  88.     short            thisCode,        thisMenu,    thisItem,    MainKey;
  89.     long            thisResult;
  90.     Rect            thisRect;
  91.     TEHandle        theInput;
  92.     EventRecord        thisEvent;
  93.     WindowPtr        thisWindow;
  94. /*
  95.  •        ----------------------------Program Initialization----------------------
  96.  •        First, we have to initialize all the Macintosh Toolbox Managers that we
  97.  •        will need. These initializations MUST be performed once, and ONLY once,
  98.  •        in your application. You would NOT initialize the managers if you were
  99.  •        writing a piece of code, such as an XCMD or INIT, which is not a
  100.  •        stand-alone application. It is also customary to flush any events which
  101.  •        may be pending in the event queue. These Toolbox initialization calls should
  102.  •        appear in exactly the order shown below.
  103.  •
  104.  */    
  105.     InitGraf    (&thePort);            /*Initialize Quickdraw*/
  106.     InitFonts    ();                    /*Initialize the Font Manager*/
  107.     FlushEvents    (everyEvent,0);
  108.     InitWindows    ();                    /*Initialize the Window Manager*/
  109.     InitMenus    ();                    /*Initialize the Menu Manager*/
  110.     TEInit        ();                    /*Initialize TextEdit*/
  111.     InitDialogs    (NIL);                /*Initialize the Dialog Manager*/
  112.     InitCursor    ();                    /*Initialize the cursor*/
  113. /*
  114.  •
  115.  •        Next we do whatever initialization is peculiar to our program. In our
  116.  •        case, we set up our menus and initialize our global and main() variables.
  117.  •        Init_ApplicationMenus() is in the file MenuControl.c, while Init_Variables()
  118.  •        is listed in this file after main().
  119.  •
  120.  */    
  121.     Init_ApplicationMenus();
  122.     Init_Variables();
  123.     Init_Windows();
  124.  
  125.     Quitting     =    FALSE;        /*We don't want to quit yet!*/
  126.     theInput         =    NIL;
  127.     
  128. /*
  129.  •        
  130.  •        Typically a program would also at this point find out information about
  131.  •        the hardware and system software environment currently running it. This
  132.  •        information is necessary so the program can either adjust to the
  133.  •        environment, or advise the user that it cannot adjust to the environment,
  134.  •        and gracefully quit.
  135.  •
  136.  •        For example, some things your program might want to know are: the number
  137.  •        of monitors, color/grayscale/monochrome, depth of color or grayscale,
  138.  •        ROM version, system version, and HFS or MFS file system.
  139.  •
  140.  •        Our program here assumes at least System 7 and a color monitor. A monochrome
  141.  •        monitor will not display the periodic table grid.
  142.  •        
  143. */
  144.  
  145. /*
  146.  •        ----------------------------Main Event Loop----------------------------
  147. */
  148.  
  149.     do
  150.     {
  151. /*
  152.  •        We call our function Do_TEIdle, which itself calls the Toolbox function
  153.  •        TEIdle so that any TextEdit insertion points will blink properly. We don't
  154.  •        have any need for this in this application. Here, we choose to remove all
  155.  •        functionality from Do_TEIdle() in WindowControl.c. Alternatively, we
  156.  •        could have just removed the call to Do_TEIdle() instead.
  157. */
  158.         Do_TEIdle    (theInput);
  159.  
  160. /*
  161.  •        Now call the Toolbox function WaitNextEvent, which is the core of every
  162.  •        Macintosh program. WaitNextEvent places the next event record into
  163.  •        thisEvent and pops that event off of the "First in, first out" event queue.
  164.  •        "everyEvent" is a system constant which tells WaitNextEvent we want to
  165.  •        retrieve all events, no matter what kind. Activate/deactivate events are
  166.  •        first priority, while update events are given last priority. (Update
  167.  •        events are generated by the system to tell us part of the screen needs
  168.  •        redrawing; activate/deactivate events tell us the front-most window
  169.  •        is changing.) 30 is the maximum number of ticks we are willing to be suspended
  170.  •        in the background without at least being passed a null event from the system.
  171.  */
  172.             
  173.  
  174.         if    (WaitNextEvent    (everyEvent,&thisEvent,30,NIL))
  175.         {
  176. /*
  177.  •        Now we determine what the user did, and respond accordingly. Constants
  178.  •        such as mouseDown and keyDown are defined by the Macintosh Toolbox. THINK C
  179.  •        implements them exactly as shown in Inside Macintosh, even though
  180.  •        the convention in C is to name constants in all upper case.
  181. */
  182.             thisCode = FindWindow    (thisEvent.where, &thisWindow);
  183.  
  184.             switch (thisEvent.what)
  185.             {
  186.                 case mouseDown:        /*If the event was a mousedown*/
  187.                 {
  188. /*
  189.  •        In what part of the screen or window did the mouse event occur?
  190.  •        (Toolbox constants for screen parts include: inMenuBar,
  191.  •        inDrag (the drag region of an application window), inGoAway (the
  192.  •        close box of an application window), inContent (in the content region
  193.  •        of an application window), and inSysWindow (in a desk accessory window)).
  194. */
  195.  
  196.                     if (thisCode == inMenuBar)
  197.                     {
  198. /*
  199.  •        If the mouseDown event was in the menubar, we decode it using the Toolbox
  200.  •        function MenuSelect, and pass the results to our menu handling routine.
  201.  •        MenuSelect also takes care of highlighting and flashing the menu items.
  202. */
  203.                         thisResult         =    MenuSelect(thisEvent.where);
  204.                         thisMenu        =    HiWord    (thisResult);
  205.                         thisItem        =    LoWord    (thisResult);
  206.                         Handle_TheMenus    (thisMenu,thisItem);
  207.                     }
  208.                     
  209.                     else    if ((thisCode == inDrag)&&(thisWindow != NIL))
  210.                     {
  211. /*
  212.  •        If the mouseDown event is in the drag region of the our window, we use
  213.  •        the Toolbox function DragWindow to drag it around, taking care not to
  214.  •        let the window get dragged completely to the edge of the screen.
  215.  •        This would need to be modified to handle multiple monitors.
  216. */
  217.                         thisRect.left    =    qd.screenBits.bounds.left    + 10;
  218.                         thisRect.right    =    qd.screenBits.bounds.right    - 10;
  219.                         thisRect.top    =    qd.screenBits.bounds.top    + 10;
  220.                         thisRect.bottom    =    qd.screenBits.bounds.bottom    - 10;
  221.                         DragWindow    (thisWindow, thisEvent.where, &thisRect);
  222.                     }
  223.                     
  224.                     else    if (thisCode == inGoAway)
  225.                     {
  226. /*
  227.  •        If the mouseDown was in the close box of the window, we monitor it with
  228.  •        the Toolbox function TrackGoAway. Like DragWindow, TrackGoAway does not
  229.  •        return until the mouse is released. TrackGoAway takes care of producing
  230.  •        the little starburst in the close box when the mouse is within the close
  231.  •        box, and removing the starburst when the mouse is outside the close box.
  232.  •        If the mouse is within the close box when the mouse is released,
  233.  •        TrackGoAway returns TRUE, in which case we call our routine to close
  234.  •        the window.
  235. */
  236.                         stillInGoAway = TrackGoAway(thisWindow,thisEvent.where);
  237.                         if (stillInGoAway == TRUE)    Close_Window    (thisWindow);
  238.                     }
  239.                     
  240.                     else    if (thisCode == inContent)
  241.                     {
  242. /*
  243.  •        If the mouseDown was in the content region of our window (as opposed to
  244.  •        its frame, or outside the window altogether) we make it active if it is
  245.  •        not already, and perform our window handling routines.
  246. */
  247.                         if (thisWindow != FrontWindow())    SelectWindow    (thisWindow);
  248.                         Do_Window        (thisWindow,&thisEvent);
  249.                         break;
  250.                     }
  251.  
  252.                     else    if (thisCode == inSysWindow)    SystemClick    (&thisEvent, thisWindow);
  253.                     break;
  254.                 }
  255. /*
  256.  •        Handle keyDown and autoKey events. Note that contrary to Listing 5 in
  257.  •        the original article, Do_PeriodicChart() is no longer responsible for
  258.  •        handling keyboard events. That is now the job of a new function, Do_Key().
  259.  •        When Do_PeriodicChart() handled both types of events, the program
  260.  •        inquired whether an event was a mouse event or keyboard event twice:
  261.  •        once in the main event loop, and once in the Do_PeriodicChart function.
  262.  •        Handling keyboard events in a separate function is a better arrangement.
  263. */
  264.                 case keyDown:
  265.                 case autoKey:
  266.                 {
  267.                     Do_Key    (FrontWindow(),&thisEvent);
  268.                     break;
  269.                 }
  270. /*
  271.  •        One of the most important parts of a program's code: Handle the Update Events.
  272. */
  273.                 case updateEvt:    
  274.                 {
  275.                     Update_Window    (&thisEvent);
  276.                     break;
  277.                 }
  278. /*
  279.  •        If there is a disk insertion event results in an error, we call the
  280.  •        Toolbox routine DIBadMount. This is the one you've seen which posts
  281.  •        alerts like "This disk is unreadable: Do you want to initialize it?"
  282.  •        followed by three buttons: Eject, One-Sided, and Two-Sided. The System
  283.  •        leaves it to the application to call DIBadMount so that disk utility
  284.  •        programs can handle bad disks with the "disk unreadable" alert being shown.
  285. */
  286.                 case diskEvt:
  287.                 {
  288.                     if (HiWord(thisEvent.message) != 0)
  289.                     { 
  290.                         thisEvent.where.h = ((qd.screenBits.bounds.right - qd.screenBits.bounds.left) / 2) - (304 / 2);
  291.                         thisEvent.where.v = ((qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) / 3) - (104 / 2);
  292.                         InitCursor();
  293.                         thisItem = DIBadMount(thisEvent.where, thisEvent.message);
  294.                     }   
  295.                     break;
  296.                 }
  297. /*
  298.  •        And finally, we activate the window clicked in if it is an activate event
  299.  •        (as determined by testing the activeFlag bit in the modifiers field of
  300.  •        the event record). We have no housekeeping to do of any kind when
  301.  •        deactivating a window, so we have no deactivating routine. More complex
  302.  •        programs may need to do things like "unhighlight" the grow box in the
  303.  •        bottom right corner of a resizable window which is being deactivated.
  304. */
  305.                 case activateEvt:
  306.                 {
  307.                     SetCursor    (&(qd.arrow));
  308.                     if ((thisWindow != NIL) && (thisEvent.modifiers & activeFlag))
  309.                     { 
  310.                         Activate_Window    (thisWindow);
  311.                     }
  312.                     break;
  313.                 }
  314.                 
  315.                 default:    break;
  316.             }
  317.         }
  318.     }
  319.     while (Quitting ==  FALSE);
  320.     
  321. /*
  322. •        Upon reaching the end of our main() function, compiler-added code and
  323. •        the operating system work to clean up after us. Our application's space
  324. •        in RAM is deallocated, so that if we have open windows or other memory
  325. •        allocated, we do not need to explicitly call DisposDialog(), DisposHandle,
  326. •        etc., to free up those blocks of memory. (Note: there are Toolbox calls
  327. •        available to allocate memory from the system heap and free multifinder
  328. •        memory, and you must explicitly clean these up before quitting.) For
  329. •        applications which save information to files, you will need to create
  330. •        a scheme for tracking changes and saving data in variables and memory
  331. •        blocks to files before quitting. Stephen Chernicoff shows a good scheme
  332. •        for doing this in volume 2 of his four volume set "Macintosh Revealed,"
  333. •        published by Hayden Books. FYI, Macintosh Revealed is written in Pascal.
  334. */
  335.  
  336. }
  337.  
  338.                                     /*end main()*/
  339.                                     
  340. /*______________________________________________________________________________
  341.                             Init_Variables()- initialize program variables
  342. ______________________________________________________________________________*/
  343.  
  344.  
  345. void    Init_Variables()
  346. {
  347.     int        loop1;
  348.  
  349. /*
  350. •        Here we are just defining a few RGB (Red Green Blue) colors, as described
  351. •        in Inside Macintosh. This is really nothing to be concerned about at this
  352. •        point. We will, however, have to make sure we draw in black, not blue, if
  353. •        we are running on a monochrome monitor. (The blue is invisible on a monochrome
  354. •        monitor. Each variable of type RGBColor has a field to describe the
  355. •        intensity of the red, green, and blue. These variables (e.g., Color_Red)
  356. •        are our program's global variables which we defined in the file MST_Globals.h.
  357. */
  358.     Color_Red.red        =    65535;
  359.     Color_Red.green        =    0;
  360.     Color_Red.blue        =    0;
  361.  
  362.     Color_Blue.red        =    0;
  363.     Color_Blue.green    =    0;
  364.     Color_Blue.blue        =    65535;
  365.  
  366.     Color_Green.red        =    0;
  367.     Color_Green.green    =    65535;
  368.     Color_Green.blue    =    0;
  369.  
  370.     Color_Black.red        =    0;
  371.     Color_Black.green    =    0;
  372.     Color_Black.blue    =    0;
  373.  
  374.     Color_White.red        =    0;
  375.     Color_White.green    =    0;
  376.     Color_White.blue    =    0;
  377.  
  378.     Color_LtRed.red        =    65535;
  379.     Color_LtRed.green    =    32767;
  380.     Color_LtRed.blue    =    32767;
  381.  
  382.     Color_LtGreen.red    =    32767;
  383.     Color_LtGreen.green    =    65535;
  384.     Color_LtGreen.blue    =    32767;
  385.  
  386.     Color_LtBlue.red    =    32767;
  387.     Color_LtBlue.green    =    32767;
  388.     Color_LtBlue.blue    =    65535;
  389.     
  390. /*
  391.  •        Now we set up the coordinates for the rectangles we need to
  392.  •        draw the periodic chart. The coordinates are all local to the window
  393.  •        into which we will draw the chart; i.e., we will use the coordinates as
  394.  •        offsets down and to the right of the top left corner of the window. The
  395.  •        top left corner of the window is coordinate (0,0) in local coordinates.
  396.  •
  397.  •        PeriodicRects[] is a global variable array which we defined in MST_Globals.h.
  398.  •        Each array element is of type Rect, a Quickdraw struct defined in Inside
  399.  •        Macintosh consisting of four QuickDraw coordinates. The fields of a Rect are
  400.  •        top, left, bottom, and right.
  401.  •
  402.  •        Each element of the array has the same number as the atomic element it
  403.  •        corresponds to. We skip PeriodicRects[0] for this reason. BoxSize is a
  404.  •        constant defined in MST_Defines.h. In this way we can change the size of the
  405.  •        periodic chart just by making one change in the program.
  406.  •
  407.  •        Of course there are many other schemes to accomplish our task of drawing
  408.  •        a periodic chart and detecting in which element mouseclicks occur. While some
  409.  •        are much more elegant, I chose this one because it makes the algorithms for
  410.  •        drawing and detecting very explicit.
  411.  */
  412.  
  413.  /*
  414.  •        First we construct column 1
  415.  */
  416.  
  417.     PeriodicRects[1].left    =    26;                PeriodicRects[1].right        =    26    + BoxSize;
  418.     PeriodicRects[3].left    =    26;                PeriodicRects[3].right        =    26    + BoxSize;
  419.     PeriodicRects[11].left    =    26;                PeriodicRects[11].right        =    26    + BoxSize;
  420.     PeriodicRects[19].left    =    26;                PeriodicRects[19].right        =    26    + BoxSize;
  421.     PeriodicRects[37].left    =    26;                PeriodicRects[37].right        =    26    + BoxSize;
  422.     PeriodicRects[55].left    =    26;                PeriodicRects[55].right        =    26    + BoxSize;
  423.     PeriodicRects[87].left    =    26;                PeriodicRects[87].right        =    26    + BoxSize;
  424.  
  425.     PeriodicRects[1].top    =    26;                PeriodicRects[1].bottom        =    26    + BoxSize;
  426.     PeriodicRects[3].top    =    26 + 1*BoxSize;    PeriodicRects[3].bottom        =    26    + 2*BoxSize;
  427.     PeriodicRects[11].top    =    26 + 2*BoxSize;    PeriodicRects[11].bottom    =    26    + 3*BoxSize;
  428.     PeriodicRects[19].top    =    26 + 3*BoxSize;    PeriodicRects[19].bottom    =    26    + 4*BoxSize;
  429.     PeriodicRects[37].top    =    26 + 4*BoxSize;    PeriodicRects[37].bottom    =    26    + 5*BoxSize;
  430.     PeriodicRects[55].top    =    26 + 5*BoxSize;    PeriodicRects[55].bottom    =    26    + 6*BoxSize;
  431.     PeriodicRects[87].top    =    26 + 6*BoxSize;    PeriodicRects[87].bottom    =    26    + 7*BoxSize;
  432.  
  433. /*
  434. •        Then column 2
  435. */
  436.  
  437.     PeriodicRects[4].left    =    26 + BoxSize;    PeriodicRects[4].right        =    26    + 2*BoxSize;
  438.     PeriodicRects[12].left    =    26 + BoxSize;    PeriodicRects[12].right        =    26    + 2*BoxSize;
  439.     PeriodicRects[20].left    =    26 + BoxSize;    PeriodicRects[20].right        =    26    + 2*BoxSize;
  440.     PeriodicRects[38].left    =    26 + BoxSize;    PeriodicRects[38].right        =    26    + 2*BoxSize;
  441.     PeriodicRects[56].left    =    26 + BoxSize;    PeriodicRects[56].right        =    26    + 2*BoxSize;
  442.     PeriodicRects[88].left    =    26 + BoxSize;    PeriodicRects[88].right        =    26    + 2*BoxSize;
  443.  
  444.     PeriodicRects[4].top    =    26 + 1*BoxSize;    PeriodicRects[4].bottom        =    26    + 2*BoxSize;
  445.     PeriodicRects[12].top    =    26 + 2*BoxSize;    PeriodicRects[12].bottom    =    26    + 3*BoxSize;
  446.     PeriodicRects[20].top    =    26 + 3*BoxSize;    PeriodicRects[20].bottom    =    26    + 4*BoxSize;
  447.     PeriodicRects[38].top    =    26 + 4*BoxSize;    PeriodicRects[38].bottom    =    26    + 5*BoxSize;
  448.     PeriodicRects[56].top    =    26 + 5*BoxSize;    PeriodicRects[56].bottom    =    26    + 6*BoxSize;
  449.     PeriodicRects[88].top    =    26 + 6*BoxSize;    PeriodicRects[88].bottom    =    26    + 7*BoxSize;
  450.  
  451. /*
  452. •        And column 3
  453. */
  454.  
  455.     PeriodicRects[21].left    =    26 + 2*BoxSize;    PeriodicRects[21].right        =    26    + 3*BoxSize;
  456.     PeriodicRects[39].left    =    26 + 2*BoxSize;    PeriodicRects[39].right        =    26    + 3*BoxSize;
  457.     PeriodicRects[57].left    =    26 + 2*BoxSize;    PeriodicRects[57].right        =    26    + 3*BoxSize;
  458.     PeriodicRects[89].left    =    26 + 2*BoxSize;    PeriodicRects[89].right        =    26    + 3*BoxSize;
  459.  
  460.     PeriodicRects[21].top    =    26 + 3*BoxSize;    PeriodicRects[21].bottom    =    26    + 4*BoxSize;
  461.     PeriodicRects[39].top    =    26 + 4*BoxSize;    PeriodicRects[39].bottom    =    26    + 5*BoxSize;
  462.     PeriodicRects[57].top    =    26 + 5*BoxSize;    PeriodicRects[57].bottom    =    26    + 6*BoxSize;
  463.     PeriodicRects[89].top    =    26 + 6*BoxSize;    PeriodicRects[89].bottom    =    26    + 7*BoxSize;
  464.  
  465. /*
  466.  •        Now we use a for loop to construct the block of elements 22 thru 30,
  467.  •        40 thru 48, 72 thru 80, and 104 thru 112.
  468.  •
  469.  */
  470.     for    (loop1=0;loop1<9;loop1++)
  471.     {
  472.         PeriodicRects[loop1+22].left    =    26 + (3+loop1)*BoxSize;
  473.         PeriodicRects[loop1+40].left    =    PeriodicRects[loop1+22].left;
  474.         PeriodicRects[loop1+72].left    =    PeriodicRects[loop1+22].left;
  475.         PeriodicRects[loop1+104].left    =    PeriodicRects[loop1+22].left;
  476.         
  477.         PeriodicRects[loop1+22].right    =    PeriodicRects[loop1+22].left + BoxSize;
  478.         PeriodicRects[loop1+40].right    =    PeriodicRects[loop1+40].left + BoxSize;
  479.         PeriodicRects[loop1+72].right    =    PeriodicRects[loop1+72].left + BoxSize;
  480.         PeriodicRects[loop1+104].right    =    PeriodicRects[loop1+72].left + BoxSize;
  481.  
  482.         PeriodicRects[loop1+22].top        =    26 + 3*BoxSize;
  483.         PeriodicRects[loop1+40].top        =    26 + 4*BoxSize;
  484.         PeriodicRects[loop1+72].top        =    26 + 5*BoxSize;
  485.         PeriodicRects[loop1+104].top    =    26 + 6*BoxSize;
  486.  
  487.         PeriodicRects[loop1+22].bottom    =    26 + 4*BoxSize;
  488.         PeriodicRects[loop1+40].bottom    =    26 + 5*BoxSize;
  489.         PeriodicRects[loop1+72].bottom    =    26 + 6*BoxSize;
  490.         PeriodicRects[loop1+104].bottom    =    26 + 7*BoxSize;
  491.     }
  492.  
  493. /*
  494. •        Don't forget Helium!
  495. */
  496.  
  497.         PeriodicRects[2].left        =    26 + 17*BoxSize;
  498.         PeriodicRects[2].right        =    PeriodicRects[2].left  + BoxSize;
  499.         PeriodicRects[2].top        =    26;
  500.         PeriodicRects[2].bottom        =    26 + BoxSize;
  501.  
  502. /*
  503. •        And now for the rightmost six columns (starting with Boron and ending
  504. •        with Radon).
  505. */
  506.  
  507.     for    (loop1=0;loop1<6;loop1++)
  508.     {
  509.         PeriodicRects[loop1+5].left        =    26 + (12+loop1)*BoxSize;
  510.         PeriodicRects[loop1+13].left    =    PeriodicRects[loop1+5].left;
  511.         PeriodicRects[loop1+31].left    =    PeriodicRects[loop1+5].left;
  512.         PeriodicRects[loop1+49].left    =    PeriodicRects[loop1+5].left;
  513.         PeriodicRects[loop1+81].left    =    PeriodicRects[loop1+5].left;
  514.         
  515.         PeriodicRects[loop1+5].right    =    PeriodicRects[loop1+5].left  + BoxSize;
  516.         PeriodicRects[loop1+13].right    =    PeriodicRects[loop1+13].left + BoxSize;
  517.         PeriodicRects[loop1+31].right    =    PeriodicRects[loop1+31].left + BoxSize;
  518.         PeriodicRects[loop1+49].right    =    PeriodicRects[loop1+49].left + BoxSize;
  519.         PeriodicRects[loop1+81].right    =    PeriodicRects[loop1+81].left + BoxSize;
  520.  
  521.         PeriodicRects[loop1+5].top        =    26 + 1*BoxSize;
  522.         PeriodicRects[loop1+13].top        =    26 + 2*BoxSize;
  523.         PeriodicRects[loop1+31].top        =    26 + 3*BoxSize;
  524.         PeriodicRects[loop1+49].top        =    26 + 4*BoxSize;
  525.         PeriodicRects[loop1+81].top        =    26 + 5*BoxSize;
  526.  
  527.         PeriodicRects[loop1+5].bottom    =    26 + 2*BoxSize;
  528.         PeriodicRects[loop1+13].bottom    =    26 + 3*BoxSize;
  529.         PeriodicRects[loop1+31].bottom    =    26 + 4*BoxSize;
  530.         PeriodicRects[loop1+49].bottom    =    26 + 5*BoxSize;
  531.         PeriodicRects[loop1+81].bottom    =    26 + 6*BoxSize;
  532.     }
  533.  
  534. /*
  535. •        And at last Cerium thru Lutetuim and Thorium thru Lawrencium.
  536. */
  537.  
  538.     for    (loop1=0;loop1<14;loop1++)
  539.     {
  540.         PeriodicRects[loop1+58].left    =    26 + (3+loop1)*BoxSize;
  541.         PeriodicRects[loop1+90].left    =    PeriodicRects[loop1+58].left;
  542.         
  543.         PeriodicRects[loop1+58].right    =    PeriodicRects[loop1+58].left    + BoxSize;
  544.         PeriodicRects[loop1+90].right    =    PeriodicRects[loop1+90].left    + BoxSize;
  545.  
  546.         PeriodicRects[loop1+58].top        =    26 + 8*BoxSize;
  547.         PeriodicRects[loop1+90].top        =    26 + 9*BoxSize;
  548.  
  549.         PeriodicRects[loop1+58].bottom    =    26 + 9*BoxSize;
  550.         PeriodicRects[loop1+90].bottom    =    26 + 10*BoxSize;
  551.     }
  552.     
  553. /*
  554.  •        Now our scheme requires one small adjustment to the rects we have
  555.  •        constructed so our periodic chart will look right when we draw it.
  556.  •        QuickDraw coordinates are pure mathematical coordinates. That is,
  557.  •        a QuickDraw point is a mathematically pure, dimensionless point. It is
  558.  •        _not_ a pixel, which has a width (of 1) and height (of 1). FrameRect
  559.  •        does all of its drawing _inside_ the coordinates you specify. So we will
  560.  •        draw the row of pixels _above_ the boundary separating Hydrogen and Lithium
  561.  •        when we draw our Hydrogen box, and below the boundary when we
  562.  •        draw our Lithium box. That would make a line two pixels wide, which we
  563.  •        do not want. So we just increase the right and bottom of each rectangle
  564.  •        by one to make everything draw correctly.
  565.  •        
  566.  */
  567.  
  568.     for    (loop1=1;loop1<=Max_NumElements;loop1++)
  569.     {
  570.         PeriodicRects[loop1].right++;
  571.         PeriodicRects[loop1].bottom++;
  572.     }
  573.         
  574. }
  575.     
  576.                                     /*end Init_Variables()*/
  577.  
  578.     
  579.     
  580.     
  581.     
  582.     
  583.     
  584.     
  585.     
  586.     
  587.  
  588.